import datetime
import json
import uuid
import base64
from django.shortcuts import HttpResponse
from rest_framework import mixins, status, viewsets
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.views import JSONWebTokenAPIView

from core.wchat.wx_base import mc
from apps.coffee.models import CoffeeOrder, CardBagOrders
from apps.user_operation.permissions import IsOwnerOrReadOnly
from core.tools.FormatXmlArray import FormatXmlArray
from .authentication import MyJSONWebTokenAuthentication
from .mini_base import wx_pay, wechat_client
from .mini_serializers import WXLoginSerializer, TelEncryptedSerializer, WeChatOrderSerializer
from .models import WxPayOrder

jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER


# 微信注册登录
class WXLoginRegisterViewSet(JSONWebTokenAPIView):
    serializer_class = WXLoginSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            serializer.save()
            user = serializer.object.get('user') or request.user
            token = serializer.object.get('token')
            if user and token:
                response_data = jwt_response_payload_handler(token, user, request)
                response = Response(response_data)
                if api_settings.JWT_AUTH_COOKIE:
                    expiration = (datetime.datetime.utcnow() +
                                  api_settings.JWT_EXPIRATION_DELTA)
                    response.set_cookie(api_settings.JWT_AUTH_COOKIE,
                                        token,
                                        expires=expiration,
                                        httponly=True)
                print(response, "微信openid登录")
                return response
            else:
                openid = serializer.object.get('openid')
                return Response({"openid": openid})

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# 微信解密手机号
class EncryptedTelViewSet(JSONWebTokenAPIView):
    serializer_class = TelEncryptedSerializer

    def post(self, request, *args, **kwargs):
        print(request.data)
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            serializer.save()
            user = serializer.object.get('user')
            token = serializer.object.get('token')
            response_data = jwt_response_payload_handler(token, user, request)
            response = Response(response_data)
            if api_settings.JWT_AUTH_COOKIE:
                expiration = (datetime.datetime.utcnow() +
                              api_settings.JWT_EXPIRATION_DELTA)
                response.set_cookie(api_settings.JWT_AUTH_COOKIE,
                                    token,
                                    expires=expiration,
                                    httponly=True)
            print(response, "手机号")
            return response
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# 统一下单(去支付)
class WeChatOrderViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    permission_classes = (IsOwnerOrReadOnly, IsAuthenticated)
    authentication_classes = (MyJSONWebTokenAuthentication, SessionAuthentication)
    serializer_class = WeChatOrderSerializer

    def create(self, request, *args, **kwargs):
        print("WeChatOrderViewSet xia dan", request.data)
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        wx_order_instance = self.perform_create(serializer)
        data = wx_pay.jsapi.get_jsapi_params(wx_order_instance.prepay_id)
        data["out_trade_no"] = wx_order_instance.out_trade_no
        print(data, "小程序下单返回统一结果")
        return Response(data, status=status.HTTP_201_CREATED)

    def perform_create(self, serializer):
        return serializer.save()


# 小程序动态二维码
class WxaCodApiViewSet(APIView):
    # permission_classes = (IsOwnerOrReadOnly, IsAuthenticated)
    # authentication_classes = (MyJSONWebTokenAuthentication, SessionAuthentication)

    def get(self, request):
        scene = request.query_params.get("scene")
        page = request.query_params.get("page")
        str_encode = request.query_params.get("str_encode")
        if str_encode == "N":  # 如果不需要加密的话
            response = wechat_client.wxa.get_wxa_code_unlimited(scene, page=page)
            content = b"data:image/png;base64," + base64.b64encode(response.content)
            return Response({"image": content}, status=status.HTTP_201_CREATED)
        else:
            key = uuid.uuid1().hex
            mc.set(key, scene, 3600 * 24 * 7)
            response = wechat_client.wxa.get_wxa_code_unlimited(key, page=page)
            # url = oss_upload_file(response.content)
            # return Response({"url": url})
            content = b"data:image/png;base64," + base64.b64encode(response.content)
            return Response({"image": content}, status=status.HTTP_201_CREATED)


# 微信回调通知
def we_chat_notify(request):
    if request.method == "POST":
        body = request.body
        print(body, "body")
        req_dict = wx_pay.parse_payment_result(body)
        print(req_dict, "print weChat pay result")
        check_result = wx_pay.check_signature(req_dict)
        if check_result:
            if req_dict.get("result_code") == "SUCCESS" and req_dict.get("return_code") == "SUCCESS":
                out_trade_no = req_dict.get("out_trade_no")
                wx_pay_obj = WxPayOrder.objects.get(out_trade_no=out_trade_no)
                total_fee = req_dict.get("total_fee")
                # 微信通知钱和要付的钱一致
                if wx_pay_obj.is_pay == 1:
                    re = {"return_code": "SUCCESS", "return_msg": "OK"}
                    re = FormatXmlArray.array_to_xml(re)
                    return HttpResponse(re)
                if total_fee == wx_pay_obj.total_fee:
                    # 更新订单
                    if wx_pay_obj.model == "coffee":
                        order_instance = CoffeeOrder.objects.get(out_trade_no=out_trade_no)
                        pay_type = 98
                        if req_dict.get("attach"):
                            pay_type = req_dict.get("attach")
                        wx_pay_obj.update_order_notify_data(req_dict)
                        cash_fee = req_dict.get("cash_fee")
                        bank_code = req_dict.get("bank_type")
                        order_instance.update_result(pay_type=pay_type, total_fee=total_fee, payment=cash_fee, bank_code=bank_code)
                        re = {"return_code": "SUCCESS", "return_msg": "OK"}
                        re = FormatXmlArray.array_to_xml(re)
                        return HttpResponse(re)
                    elif wx_pay_obj.model == "cardBag":
                        order_instance = CardBagOrders.objects.get(out_trade_no=out_trade_no)
                        pay_type = 98
                        if req_dict.get("attach"):
                            pay_type = req_dict.get("attach")
                        order_instance.update_card_bag_order(pay_type=pay_type)
                        wx_pay_obj.update_order_notify_data(req_dict)
                        re = {"return_code": "SUCCESS", "return_msg": "OK"}
                        re = FormatXmlArray.array_to_xml(re)
                        return HttpResponse(re)
                    else:
                        raise Exception("小程序支付，但不是coffee，也没上其他的")
                else:
                    return HttpResponse("订单金额不一致,需要退钱联系管理员")
            raise Exception("result_code error or result_code error")
        else:
            raise Exception("支付通知数据错误")
    else:
        return HttpResponse("hello world")
